home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / pxm_ray / pxm_ray.lha / pxm-ray / pixel_intersect.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-09  |  3.7 KB  |  188 lines

  1.  
  2. /*
  3.  * Intersection routines
  4.  */
  5.  
  6. /*
  7.  *    (c) 1988 by George Kyriazis
  8.  */
  9.  
  10. #include    "ray.h"
  11. #include    <math.h>
  12. #include    "vector.h"
  13. #include    "msg.h"
  14.  
  15. struct    obj    *calc_addr();
  16. struct    obj    *obj_addr();
  17.  
  18. /* 
  19.  * Intersect ray with sphere
  20.  */
  21. struct    intersect    sphere(obj, r)
  22. struct    obj    *obj;
  23. struct    ray    r;
  24. {
  25.     struct    vector    v;
  26.     struct    vector    n;    /* normal vector */
  27.     struct    intersect    i;
  28.     register    double    b, d;
  29.     double    c;
  30.     double    sol1, sol2;
  31.     struct    vector    center;
  32.  
  33.     i.obj = NULL;
  34.  
  35.     center = svproduct(time, obj->time);
  36.     center = vadd( obj->data.sphere.center, center);
  37.     v = vsub( r.pos, center);
  38.     b = 2 * vdot( r.dir, v );
  39.     c = vdot(v, v) - obj->data.sphere.radius;
  40.  
  41.     d = b * b - 4 * c;
  42.     if( d < 0 )
  43.         return i;
  44.     d = sqrt(d);
  45.     sol1 = ( -b + d ) / 2;
  46.     sol2 = ( -b - d ) / 2;
  47.     if( sol1 <= 0 )
  48.         sol1 = sol2;
  49.     if( sol2 <= 0 )
  50.         sol2 = sol1;
  51.     i.t = (sol1 < sol2) ? sol1 : sol2 ;
  52. /* if intersection is behind eye */
  53.     if(i.t <= 0)
  54.         return i;
  55.     i.obj = obj;    
  56.  
  57. /* calculate the normal.  It is just the direction of the radius */
  58.     i.n = vsub( vadd( r.pos, svproduct(i.t, r.dir) ),
  59.         center);
  60.     NORM(i.n);
  61.  
  62.     return i;
  63. }
  64.  
  65. /*
  66.  * intersect ray with a quadrangle
  67.  */
  68. struct    intersect    quad(obj, r)
  69. struct    obj    *obj;
  70. struct    ray    r;
  71. {
  72.     struct    intersect    i;
  73.     double    x0, y0, z0;
  74.     double    dx1, dy1, dz1, dx2, dy2, dz2, qx, qy, qz;
  75.     double    alpha, a, b, t;
  76.     double    d, dalpha, da, db;
  77.     struct    vector    n;
  78.     double    pdx, pdy, pdz;
  79.     double    size;
  80.     struct    vector    timev;
  81.  
  82.     i.obj = NULL;
  83.  
  84.     timev = svproduct( time, obj->time );
  85.  
  86.     x0 = obj->data.quad.p1.x;
  87.     y0 = obj->data.quad.p1.y;
  88.     z0 = obj->data.quad.p1.z;
  89.     dx1 = x0 - obj->data.quad.p2.x;
  90.     dy1 = y0 - obj->data.quad.p2.y;
  91.     dz1 = z0 - obj->data.quad.p2.z;
  92.     dx2 = x0 - obj->data.quad.p3.x;
  93.     dy2 = y0 - obj->data.quad.p3.y;
  94.     dz2 = z0 - obj->data.quad.p3.z;
  95.     qx = r.dir.x;
  96.     qy = r.dir.y;
  97.     qz = r.dir.z;
  98.  
  99.     d = qx * ( ( dy1 * dz2 ) - ( dy2 * dz1 ) )
  100.         - dx1 * ( ( qy * dz2 ) - ( qz * dy2 ) )
  101.         + dx2 * ( ( qy * dz1 ) - ( qz * dy1 ) ) ;
  102.  
  103. /* if no intersection */
  104.     if( ABS(d) < MINT )
  105.         return i;
  106.  
  107.     pdx = x0 - r.pos.x + timev.x;
  108.     pdy = y0 - r.pos.y + timev.y;
  109.     pdz = z0 - r.pos.z + timev.z;
  110.  
  111.     dalpha = pdx * ( ( dy1 * dz2 ) - ( dz1 * dy2 ) )
  112.         - dx1 * ( ( pdy * dz2 ) - ( pdz * dy2 ) )
  113.         + dx2 * ( ( pdy * dz1 ) - ( pdz * dy1 ) ) ;
  114.     alpha = dalpha / d;
  115.  
  116. /* if intersection behind the eye */
  117.     if( alpha <= 0 )
  118.         return i;
  119.  
  120.     da = qx * ( ( pdy * dz2 ) - ( pdz * dy2 ) )
  121.         - pdx * ( ( qy * dz2 ) - ( qz * dy2 ) )
  122.         + dx2 * ( ( qy * pdz ) - ( qz * pdy ) ) ;
  123.  
  124.     db = qx * ( ( dy1 * pdz ) - ( dz1 * pdy ) )
  125.         - dx1 * ( ( qy * pdz ) - ( qz * pdy ) )
  126.         + pdx * ( ( qy * dz1 ) - ( qz * dy1 ) );
  127.  
  128.     a = da / d;
  129.     b = db / d;
  130.  
  131. /* check if intersection within quad */
  132.     if( ( a < 0 ) || ( a > 1 ) )
  133.         return i;
  134.     if( ( b < 0 ) || ( b > 1 ) )
  135.         return i;
  136.  
  137. /* assign the object */
  138.     i.obj = obj;
  139.     i.t = alpha;
  140. /* normal to the plane */
  141.     i.n.x = dy1 * dz2 - dy2 * dz1;
  142.     i.n.y = - ( dx1 * dz2 - dx2 * dz1 );
  143.     i.n.z = dx1 * dy2 - dx2 * dy1;
  144.     NORM ( i.n );
  145.  
  146.     return i;
  147. }
  148.  
  149.  
  150. struct    intersect    intersect(r)
  151. struct    ray    r;
  152. {
  153.     register    int    i;
  154.     struct    intersect    inter, intermin;
  155.     struct    obj    *obj;
  156.  
  157.     intermin.obj = NULL;
  158.  
  159.     for(i = 0; i < noo; i++) {
  160.         objtestline++;
  161.         obj = obj_addr(i, sizeof(struct obj));
  162.         switch( obj->type ) {
  163.             case SPHERE:
  164.                 inter = sphere( obj, r);
  165.                 break;
  166.             case SQUARE:
  167.                 inter = quad( obj, r);
  168.                 break;
  169.             default:
  170.                 break;
  171.         }
  172. /* update the minimum intersection distance if the new intersection  */
  173. /* exists (ray intersects the object), and the intersection distance */
  174. /* is smaller that the one logged and also the object intersected is */
  175. /* not the object that the ray is originating from.                  */
  176.         if( inter.obj &&
  177.             ( !intermin.obj || 
  178.                 (inter.t < intermin.t) ) &&
  179.             ( inter.obj != r.obj ) ) {
  180.             intermin = inter;
  181.             intermin.objaddr = calc_addr(i, sizeof(struct obj));
  182.         }
  183.     }
  184.  
  185.     return intermin;
  186. }
  187.  
  188.